/*---------------------------------------------------------------------------*\
  =========                 |
  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
   \\    /   O peration     | Website:  https://openfoam.org
    \\  /    A nd           | Copyright (C) 2023 OpenFOAM Foundation
     \\/     M anipulation  |
-------------------------------------------------------------------------------
License
    This file is part of OpenFOAM.

    OpenFOAM is free software: you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    for more details.

    You should have received a copy of the GNU General Public License
    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.

Class
    Foam::mergePatchPairs

Description
    Class to stitch mesh by merging patch-pairs

SourceFiles
    mergePatchPairs.C

\*---------------------------------------------------------------------------*/

#ifndef mergePatchPairs_H
#define mergePatchPairs_H

#include "polyMesh.H"

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

namespace Foam
{

class fvMesh;
class polyTopoChange;
class polyPatchIntersection;

/*---------------------------------------------------------------------------*\
                     Class mergePatchPairs Declaration
\*---------------------------------------------------------------------------*/

class mergePatchPairs
{
    // Private data

        polyMesh& mesh_;

        const scalar snapTol_;

        mutable labelList newPoints_;


    // Private member functions

        //- Return patch index of given patch name
        //  Throw a fatal error if the patch name is not found
        label findPatchIndex(const word& patchName) const;

        //- Return the patch index pairs
        //  corresponding to the give patch name pairs
        Pair<label> findPatchIndices
        (
            const Pair<word>& patchNamePair
        ) const;

        //- Set the patchPairs_ patch index pair list
        //  from the patchNamePairs_ patch name pair list
        List<Pair<label>> patchPairs
        (
            const List<Pair<word>>& patchNamePairs
        ) const;

        //- Remove all the points corresponding to the patch pairs to be merged
        void removePoints
        (
            polyTopoChange& meshMod,
            const List<Pair<label>>& patchPairs
        ) const;

        //- Add the points generated by the patch intersection
        void addPoints
        (
            polyTopoChange& meshMod,
            const polyPatchIntersection& intersection
        ) const;

        //- Remove all the faces of the source and target patches to me merged
        void removeFaces
        (
            polyTopoChange& meshMod,
            const polyPatchIntersection& intersection
        ) const;

        //- Map face from patch-local point indices to global mesh point indices
        face mapFace(const face& f) const;

        //- Add a new internal and patch face to the mesh
        void addFaces
        (
            polyTopoChange& meshMod,
            const polyPatchIntersection& intersection
        ) const;

        void addEdgeAddedPoints
        (
            HashTable<labelList, edge, Hash<edge>>& edgeAddedPoints,
            const primitivePatch& patch,
            const List<DynamicList<label>>& patchEdgeAddedPoints
        ) const;

        //- Update the point indices of the changed points in the pointMap
        void updatePoints
        (
            labelList& pointMap,
            const primitivePatch& patch,
            const labelList& pointPoints
        ) const;

        //- Modify the edges of existing edge-connected faces
        //  by changing the end-point and adding any additional points
        //  and point-connected faces by updating the point indices
        void modifyFaces
        (
            polyTopoChange& meshMod,
            const polyPatchIntersection& intersection
        ) const;

        //- Intersect the given pair of patches and insert all face changes
        //  into meshMod
        void intersectPatchPair
        (
            polyTopoChange& meshMod,
            const polyPatch& srcPatch,
            const polyPatch& tgtPatch
        ) const;

        //- Merge all the given patch pairs
        //  returning the polyTopoChangeMap for subsequent field mapping
        autoPtr<polyTopoChangeMap> merge
        (
            const List<Pair<label>>& patchPairIndices
        ) const;

        //- Return true if the points of patchi are connected to any
        //  of the patches already tested
        bool connected
        (
            boolList& patchPoints,
            const label patchi
        ) const;

        //- Merge all the given patch pairs
        //  and update all the fields cached in the given mesh
        template<class Mesh>
        inline void merge
        (
            Mesh& mesh,
            const List<Pair<word>>& patchPairNames
        ) const;


public:

    // Static Data Members

        ClassName("mergePatchPairs");


    // Constructors

        mergePatchPairs
        (
            polyMesh& mesh,
            const List<Pair<word>>& patchPairNames,
            const scalar snapTol
        );

        mergePatchPairs
        (
            fvMesh& mesh,
            const List<Pair<word>>& patchPairNames,
            const scalar snapTol
        );
};


// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

} // End namespace Foam

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

#endif

// ************************************************************************* //
